package com.crm.miaohe.service;

import com.crm.miaohe.common.ApplicationConstant;
import com.crm.miaohe.controller.PageResponse;
import com.crm.miaohe.controller.customer.request.CustomerBatchUpdateParams;
import com.crm.miaohe.controller.customer.request.CustomerParams;
import com.crm.miaohe.controller.customer.request.CustomerQueryParams;
import com.crm.miaohe.exception.ErpBusinessException;
import com.crm.miaohe.kdcloud.model.Customer;
import com.crm.miaohe.kdcloud.model.NumberRecord;
import com.crm.miaohe.mapper.TblCustomerApiMapper;
import com.crm.miaohe.mapper.TblCustomerMapper;
import com.crm.miaohe.mapper.TblDepositDetailsMapper;
import com.crm.miaohe.model.TblCustomer;
import com.crm.miaohe.model.TblCustomerExample;
import com.crm.miaohe.model.TblDepositDetails;
import com.crm.miaohe.utils.StringUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import reactor.util.function.Tuple2;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class CustomerServiceImpl implements CustomerService {

    private final TblCustomerMapper customerMapper;

    private final TblCustomerApiMapper customerApiMapper;

    private final PasswordEncoder passwordEncoder;

    private final K3CloudApiService k3CloudApiService;
    
    private final TblDepositDetailsMapper depositDetailsMapper;

    public CustomerServiceImpl(TblCustomerMapper customerMapper,
                               TblCustomerApiMapper customerApiMapper,
                               PasswordEncoder passwordEncoder,
                               K3CloudApiService k3CloudApiService,
                               TblDepositDetailsMapper depositDetailsMapper) {
        this.customerMapper = customerMapper;
        this.customerApiMapper = customerApiMapper;
        this.passwordEncoder = passwordEncoder;
        this.k3CloudApiService = k3CloudApiService;
        this.depositDetailsMapper = depositDetailsMapper;
    }

    @Override
    public void addCustomer(CustomerParams params) {
        // 判断两次输入密码是否相同
        String password = params.getPassword();
        if (!password.equals(params.getPasswordConfirm())) {
            log.error("Password and PasswordConfirm are different. password: {}; passwordConfirm: {}",
                    password, params.getPasswordConfirm());
            throw new ErpBusinessException(HttpStatus.BAD_REQUEST,
                    new IllegalArgumentException("Password and PasswordConfirm have to be same."),
                    ApplicationConstant.CUS001,
                    params.getPassword(), params.getPasswordConfirm());
        }
        // 判断当前电话号码是否被注册过
        TblCustomerExample example = new TblCustomerExample();
        example.createCriteria().andPhoneNumberEqualTo(params.getPhoneNumber()).andDeletedEqualTo(false);
        long count = customerMapper.countByExample(example);
        if (count > 0) {
            throw new ErpBusinessException(HttpStatus.BAD_REQUEST, ApplicationConstant.CUS002, params.getPhoneNumber());
        }
        example.clear();
        example.createCriteria().andNameEqualTo(params.getName()).andDeletedEqualTo(false);
        count = customerMapper.countByExample(example);
        if (count > 0) {
            throw new ErpBusinessException(HttpStatus.BAD_REQUEST, ApplicationConstant.CUS004, params.getName());
        }

        TblCustomer customer = new TblCustomer();
        BeanUtils.copyProperties(params, customer);
        customer.setDeleted(false);
        customer.setApproved(false);
        customer.setLocked(false);
        customer.setPassword(passwordEncoder.encode(params.getPassword()));
        if(params.getFreightFee()!=null && params.getFreightFee() > 0){
            customer.setFreight(1);
        }else{
            customer.setFreight(0);
        }
        if (customer.getWuliuOrder() == null) {
            customer.setWuliuOrder(0);
        }
        customerMapper.insert(customer);
    }

    @Override
    public void updateCustomer(CustomerParams params) {
        TblCustomer customer = new TblCustomer();

        // 判断当前电话号码是否被注册过
        TblCustomerExample example = new TblCustomerExample();
        example.createCriteria().andPhoneNumberEqualTo(params.getPhoneNumber()).andDeletedEqualTo(false).andIdNotEqualTo(params.getId());
        long count = customerMapper.countByExample(example);
        if (count > 0) {
            throw new ErpBusinessException(HttpStatus.BAD_REQUEST, ApplicationConstant.CUS002, params.getPhoneNumber());
        }
        BeanUtils.copyProperties(params, customer);
        if(params.getFreightFee()!=null && params.getFreightFee() > 0){
            customer.setFreight(1);
        }else{
            customer.setFreightFee(0);
            customer.setFreight(0);
        }
        
        // 更新客户预付款增加预付款明细
        TblCustomer checkCus = customerMapper.selectByPrimaryKey(customer.getId());
        if(customer.getNoDepositOrder().equals("2") && customer.getDepositAmount() != null && !customer.getDepositAmount().equals(checkCus.getDepositAmount())) {
        	// 增加预付款明细
        	TblDepositDetails deposit = new TblDepositDetails();
        	deposit.setCustomerId(customer.getId());
        	deposit.setDataFrom("客户信息更新");
        	deposit.setAmount(customer.getDepositAmount());
        	deposit.setLockAmount(checkCus.getLockAmount());
        	deposit.setChangeType("客户直接变更");
        	
        	depositDetailsMapper.insert(deposit);
        }
        
        customerMapper.updateByPrimaryKeySelective(customer);

        // 构造向金蝶提交数据的客户实体
        TblCustomer customerNew = customerMapper.selectByPrimaryKey(customer.getId());
        // 同步过金蝶再发
        if (org.springframework.util.StringUtils.hasLength(customerNew.getCustomerNum())) {
            syncCustomer(customerNew);
        }
        
    }

    @Override
    public Map<String, Object> batchUpdateCustomer(CustomerBatchUpdateParams params) {
        TblCustomerExample example = new TblCustomerExample();
        TblCustomerExample.Criteria criteria = example.createCriteria();
        if (!ObjectUtils.isEmpty(params.getName())) {
            criteria.andNameLike(StringUtils.quoteWith(params.getName(), "%"));
        }
        if (!ObjectUtils.isEmpty(params.getPrincipal())) {
            criteria.andPrincipalEqualTo(params.getPrincipal());
        }
        if (!ObjectUtils.isEmpty(params.getPhoneNumber())) {
            criteria.andPhoneNumberEqualTo(params.getPhoneNumber());
        }
        if (!ObjectUtils.isEmpty(params.getBizCode())) {
            criteria.andBizCodeEqualTo(params.getBizCode());
        }
        if (!ObjectUtils.isEmpty(params.getOrganizationCode())) {
            criteria.andOrganizationCodeEqualTo(params.getOrganizationCode());
        }
        if (!ObjectUtils.isEmpty(params.getCustomerTypeCode())) {
            criteria.andCustomerTypeCodeEqualTo(params.getCustomerTypeCode());
        }
        if (!ObjectUtils.isEmpty(params.getCustomerKindCode())) {
            criteria.andCustomerKindCodeEqualTo(params.getCustomerKindCode());
        }

        if (!ObjectUtils.isEmpty(params.getPriceStrategy())) {
            criteria.andPriceStrategyEqualTo(params.getPriceStrategy());
        }

        if (!ObjectUtils.isEmpty(params.getWuliuCode())) {
            criteria.andWuliuCodeEqualTo(params.getWuliuCode());
        }
        if (!ObjectUtils.isEmpty(params.getShoukuanCode())) {
            criteria.andShoukuanCodeEqualTo(params.getShoukuanCode());
        }
        if (!ObjectUtils.isEmpty(params.getCompanyCode())) {
            criteria.andCompanyCodeEqualTo(params.getCompanyCode());
        }
        if (!ObjectUtils.isEmpty(params.getCreateDate())) {
            Instant instant = params.getCreateDate().toInstant();
            ZoneId zone = ZoneId.systemDefault();
            LocalDateTime startLocalDateTime = LocalDateTime.ofInstant(instant, zone);
            LocalDateTime endLocalDateTime = startLocalDateTime.plusDays(1).minusSeconds(1);
            criteria.andCreateTimeBetween(startLocalDateTime, endLocalDateTime);
        }

        criteria.andDeletedEqualTo(false);

        TblCustomer updateVal = new TblCustomer();
        updateVal.setCustomerTypeCode(params.getBatchUpdateCustomerTypeCode());
        updateVal.setCustomerTypeName(params.getBatchUpdateCustomerTypeName());

        int count = customerMapper.updateByExampleSelective(updateVal, example);
        Map<String, Object> res = new HashMap<>();
        res.put("count", count);
        res.put("res", true);
        return res;
    }

    @Override
    public PageResponse<TblCustomer> getCustomers(CustomerQueryParams params) {
        TblCustomerExample example = new TblCustomerExample();
        TblCustomerExample.Criteria criteria = example.createCriteria();
        if (!ObjectUtils.isEmpty(params.getName())) {
            criteria.andNameLike(StringUtils.quoteWith(params.getName(), "%"));
        }
        if (!ObjectUtils.isEmpty(params.getPrincipal())) {
            criteria.andPrincipalEqualTo(params.getPrincipal());
        }
        if (!ObjectUtils.isEmpty(params.getPhoneNumber())) {
            criteria.andPhoneNumberEqualTo(params.getPhoneNumber());
        }
        if (!ObjectUtils.isEmpty(params.getBizCode())) {
            criteria.andBizCodeEqualTo(params.getBizCode());
        }
        if (!ObjectUtils.isEmpty(params.getOrganizationCode())) {
            criteria.andOrganizationCodeEqualTo(params.getOrganizationCode());
        }
        if (!ObjectUtils.isEmpty(params.getCustomerTypeCode())) {
            criteria.andCustomerTypeCodeEqualTo(params.getCustomerTypeCode());
        }
        if (!ObjectUtils.isEmpty(params.getCustomerKindCode())) {
            criteria.andCustomerKindCodeEqualTo(params.getCustomerKindCode());
        }

        if (!ObjectUtils.isEmpty(params.getPriceStrategy())) {
            criteria.andPriceStrategyEqualTo(params.getPriceStrategy());
        }

        if (!ObjectUtils.isEmpty(params.getWuliuCode())) {
            criteria.andWuliuCodeEqualTo(params.getWuliuCode());
        }
        if (!ObjectUtils.isEmpty(params.getShoukuanCode())) {
            criteria.andShoukuanCodeEqualTo(params.getShoukuanCode());
        }
        if (!ObjectUtils.isEmpty(params.getCompanyCode())) {
            criteria.andCompanyCodeEqualTo(params.getCompanyCode());
        }
        if (!ObjectUtils.isEmpty(params.getCreateDate())) {
            Instant instant = params.getCreateDate().toInstant();
            ZoneId zone = ZoneId.systemDefault();
            LocalDateTime startLocalDateTime = LocalDateTime.ofInstant(instant, zone);
            LocalDateTime endLocalDateTime = startLocalDateTime.plusDays(1).minusSeconds(1);
            criteria.andCreateTimeBetween(startLocalDateTime, endLocalDateTime);
        }

        criteria.andDeletedEqualTo(false);
        PageInfo<TblCustomer> pageInfo =
                PageHelper.startPage(params.getPageNo(), params.getPageSize(), "create_time desc")
                        .doSelectPageInfo(() -> customerMapper.selectByExample(example));
        return PageResponse.<TblCustomer>builder()
                .currentPage(pageInfo.getPageNum())
                .totalPage(pageInfo.getPages())
                .totalElement(pageInfo.getTotal())
                .records(pageInfo.getList())
                .build();
    }

    @Override
    public List<TblCustomer> getApprovedCustomers() {
        TblCustomerExample example = new TblCustomerExample();
        TblCustomerExample.Criteria criteria = example.createCriteria();
        criteria.andApprovedEqualTo(true);
        return customerApiMapper.selectByExample(example);
    }

    @Override
    @Transactional
    public void approvedCustomer(Long id) {
        TblCustomer tblCustomer = new TblCustomer();
        tblCustomer.setApproved(true);
        tblCustomer.setId(id);
        customerMapper.updateByPrimaryKeySelective(tblCustomer);
        // 构造向金蝶提交数据的客户实体
        TblCustomer customer = customerMapper.selectByPrimaryKey(id);

        // 向金蝶提交数据，取回客户编码
        Tuple2<String, String> customerInfo = syncCustomer(customer);

        // 更新客户表中的金蝶客户编码
        TblCustomer var1 = new TblCustomer();
        var1.setCustomerNum(customerInfo.getT1());
        var1.setCustomerId(Integer.parseInt(customerInfo.getT2()));
        var1.setId(id);
        customerMapper.updateByPrimaryKeySelective(var1);
    }

    public Tuple2<String, String> syncCustomer(TblCustomer customer) {

        Customer kdCustomer = new Customer();

        Integer customerId = customer.getCustomerId();
        String customerNum = customer.getCustomerNum();
        if (customerId != null && customerId > 0) {
            k3CloudApiService.unAudit("BD_Customer", Map.of("Numbers", customerNum));
            kdCustomer.setFCUSTID(customerId);
        }

        // 客户名称
        kdCustomer.setFName(customer.getName());
        // 客户名称缩写
        kdCustomer.setFShortName(customer.getName());
        // 地址
        kdCustomer.setFADDRESS(customer.getAddress());
        // 电话号码
        kdCustomer.setFTEL(customer.getPhoneNumber());
        // 审核状态
        kdCustomer.setFDocumentStatus("C");

        //销售员 TODO
        NumberRecord fSellerNumberRecord = new NumberRecord();
        fSellerNumberRecord.setFNumber(customer.getBizCode());
        kdCustomer.setFSELLER(fSellerNumberRecord);
        //收款条件
        NumberRecord fRecNumberRecord = new NumberRecord();
        fRecNumberRecord.setFNumber(customer.getShoukuanCode());
        kdCustomer.setFRECCONDITIONID(fRecNumberRecord);
        //客户所属公司
        NumberRecord f_DLMH_Assistant1 = new NumberRecord();
        f_DLMH_Assistant1.setFNumber(customer.getCompanyCode());
        kdCustomer.setF_DLMH_Assistant1(f_DLMH_Assistant1);

        //客户类别FCustTypeId
        NumberRecord fCustTypeId = new NumberRecord();
        fCustTypeId.setFNumber(customer.getCustomerKindCode());
        kdCustomer.setFCustTypeId(fCustTypeId);

        //客户创建组织
        kdCustomer.setFCreateOrgId(new NumberRecord("100"));

        //客户使用组织
        kdCustomer.setFUseOrgId(new NumberRecord("100"));

        kdCustomer.setFSALDEPTID(new NumberRecord(customer.getOrganizationCode()));

        //客户分组
        NumberRecord groupNumberRecord = new NumberRecord();
        groupNumberRecord.setFNumber(customer.getCustomerTypeCode());
        kdCustomer.setFGroup(groupNumberRecord);

        //物流线路
        NumberRecord wuliuNumberRecord = new NumberRecord();
        wuliuNumberRecord.setFNumber(customer.getWuliuCode());
        kdCustomer.setF_DLMH_Assistant(wuliuNumberRecord);

        // 向金蝶提交数据，取回客户编码
        return k3CloudApiService.saveCustomer(kdCustomer);
    }

    @Override
    public void lockCustomer(Long id) {
        TblCustomer tblCustomer = new TblCustomer();
        tblCustomer.setId(id);
        tblCustomer.setLocked(true);
        customerMapper.updateByPrimaryKeySelective(tblCustomer);
    }

    @Override
    public void unlockCustomer(Long id) {
        TblCustomer tblCustomer = new TblCustomer();
        tblCustomer.setId(id);
        tblCustomer.setLocked(false);
        customerMapper.updateByPrimaryKeySelective(tblCustomer);
    }

    @Override
    public void deleteCustomer(Long id) {
        TblCustomer tblCustomer = new TblCustomer();
        tblCustomer.setId(id);
        tblCustomer.setDeleted(true);
        customerMapper.updateByPrimaryKeySelective(tblCustomer);
    }

    @Override
    public void updatePassword(CustomerParams customerParams) {
        TblCustomer tblCustomer = new TblCustomer();
        tblCustomer.setPassword(passwordEncoder.encode(customerParams.getPassword()));
        tblCustomer.setId(customerParams.getId());
        customerMapper.updateByPrimaryKeySelective(tblCustomer);
    }

    @Override
    public boolean checkPhoneNumber(CustomerParams customerParams) {
        TblCustomerExample example = new TblCustomerExample();
        example.createCriteria().andIdNotEqualTo(customerParams.getId()).andPhoneNumberEqualTo(customerParams.getPhoneNumber()).andDeletedEqualTo(false);
        return customerMapper.countByExample(example) > 0;
    }

    @Override
    public boolean checkUserName(CustomerParams customerParams) {
        TblCustomerExample example = new TblCustomerExample();
        example.createCriteria().andIdNotEqualTo(customerParams.getId()).andNameEqualTo(customerParams.getName()).andDeletedEqualTo(false);
        return customerMapper.countByExample(example) > 0;
    }

    @Override
    public TblCustomer currentUser(String username) {
        TblCustomerExample example = new TblCustomerExample();
        example.createCriteria().andPhoneNumberEqualTo(username).andDeletedEqualTo(false);
        return customerMapper.selectByExample(example).stream().findAny().orElseThrow(() -> new UsernameNotFoundException(ApplicationConstant.USERNAME_NOT_FOUND));
    }

	@Override
	public void updateDeposit(Long id, Double amount) {
		TblCustomerExample example = new TblCustomerExample();
        example.createCriteria().andCustomerIdEqualTo(id);
		TblCustomer customer = customerMapper.selectByExample(example).stream().findAny().get();
		if (customer != null) {
			customer.setDepositAmount(customer.getDepositAmount() == null ? 0 : customer.getDepositAmount() + amount);
			customer.setNoDepositOrder("2");
			customerMapper.updateByPrimaryKey(customer);
	    	
	    	// 增加预付款明细
	    	TblDepositDetails deposit = new TblDepositDetails();
	    	deposit.setCustomerId(customer.getId());
	    	deposit.setDataFrom("金蝶收款单API");
	    	deposit.setAmount(customer.getDepositAmount());
	    	deposit.setLockAmount(customer.getLockAmount());
	    	deposit.setChangeType("金蝶API接口");
	    	
	    	depositDetailsMapper.insert(deposit);
		}
	}
}
